package com.my12306.common.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.my12306.common.dao.ScheduleJobDao;
import com.my12306.common.model.po.ScheduleJobPo;
import com.my12306.common.model.vo.PageVo;
import com.my12306.common.util.PageUtils;
import com.my12306.common.util.SnowflakeIdWorker;
import com.my12306.common.util.quartz.scheduler.BaseScheduler;
import com.my12306.common.util.quartz.scheduler.CronScheduler;
import com.my12306.common.util.quartz.scheduler.ScheduleUtils;
import com.my12306.common.util.quartz.scheduler.SimpleScheduler;
import com.my12306.user.util.auth.OauthUtils;
import org.apache.commons.lang.StringUtils;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author:苏牧夕
 * @Date:2020/5/28 0:33
 * @Version 1.0
 */
@Service

public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobDao, ScheduleJobPo> implements ScheduleJobService {
    @Autowired
    private Scheduler scheduler;
    @Autowired
    private CronScheduler cronScheduler;
    @Autowired
    private SimpleScheduler simpleScheduler;
    @Autowired
    private ScheduleUtils scheduleUtils;
    @Resource
    private ScheduleJobDao scheduleJobDao;
    @Autowired
    private OauthUtils oauthUtils;

    @Override
    public PageUtils getJobListPage(PageVo pageVo) {
        List<ScheduleJobPo> list = new ArrayList<>();
        Integer page = pageVo.getPage();
        Integer limit = pageVo.getLimit();
        String likeName = pageVo.getLikeName();
        if (page == null || limit == null) {
            page = 1;
            limit = 50;
        }
        if (likeName != null && StringUtils.isNotEmpty(likeName))
            likeName = "%" + likeName + "%";
        List<ScheduleJobPo> poList = scheduleJobDao.queryListPage((page - 1) * limit, limit, likeName, ScheduleUtils.JobOperateEnum.DELETE.getValue());
        Integer count = this.baseMapper.selectCount(null);
        PageUtils pageUtils = new PageUtils(count, limit, page, poList);
        return pageUtils;
    }

    @Override
    public Boolean addCronJob(ScheduleJobPo scheduleJobPo) {
        if (scheduleJobPo.getShowStatus() == null)
            scheduleJobPo.setShowStatus(ScheduleUtils.JobOperateEnum.START.getValue());
        scheduleJobPo.setCreateDate(new Date());
        scheduleJobPo.setUpdateDate(new Date());
        scheduleJobPo.setUserId(oauthUtils.getUserId());
        scheduleJobPo.setJobId(SnowflakeIdWorker.generateId());
        scheduleJobDao.insert(scheduleJobPo);
        log.error("========>addCronJob:"+scheduleJobPo);
        try {
            Boolean flag = scheduleUtils.addJob(cronScheduler, scheduler, scheduleJobPo);
            log.error("添加定时任务的状态："+flag);
            return flag;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("Exception:");
            this.baseMapper.deleteById(scheduleJobPo.getJobId());
            return false;
        }
    }


    // TODO: 2020/5/29
    @Override
    public Boolean addSimpleJob(ScheduleJobPo scheduleJobPo) {
        return scheduleUtils.addJob(simpleScheduler, scheduler, scheduleJobPo);
    }

    @Override
    @Transactional
    public Boolean updateCronJob(ScheduleJobPo scheduleJobPo) {
        Boolean flag = scheduleUtils.updateJob(cronScheduler, scheduler, scheduleJobPo);
        if (flag) {
            this.baseMapper.updateById(scheduleJobPo);
        }
        return flag;
    }

    // TODO: 2020/5/29
    @Override
    public Boolean updateSimpleJob(ScheduleJobPo scheduleJobPo) {
        return scheduleUtils.updateJob(simpleScheduler, scheduler, scheduleJobPo);
    }


    @Override
    @Transactional
    public Boolean pauseJob(List<Long> jobIds) {
        return updateJob(jobIds, ScheduleUtils.JobOperateEnum.PAUSE.getValue(), cronScheduler, scheduler);
    }

    @Override
    @Transactional
    public Boolean resumeJob(List<Long> jobIds) {
        return this.updateJob(jobIds, ScheduleUtils.JobOperateEnum.START.getValue(), cronScheduler, scheduler);
    }

    @Override
    @Transactional
    public Boolean deleteJob(List<Long> jobIds) {
        return updateJob(jobIds, ScheduleUtils.JobOperateEnum.DELETE.getValue(), cronScheduler, scheduler);
    }

    @Override
    @Transactional
    public Boolean pauseAllJob() {
        ScheduleJobPo scheduleJobPo = new ScheduleJobPo();
        scheduleJobPo.setShowStatus(ScheduleUtils.JobOperateEnum.PAUSE.getValue());
        this.baseMapper.update(scheduleJobPo, new QueryWrapper<ScheduleJobPo>().eq("show_status", ScheduleUtils.JobOperateEnum.START.getValue()));
        scheduleUtils.pauseAllJob(cronScheduler, scheduler);
        return true;
    }

    @Override
    @Transactional
    public Boolean resumeAllJob() {
        ScheduleJobPo scheduleJobPo = new ScheduleJobPo();
        scheduleJobPo.setShowStatus(ScheduleUtils.JobOperateEnum.START.getValue());
        this.baseMapper.update(scheduleJobPo, null);
        scheduleUtils.resumeAllJob(cronScheduler, scheduler);
        return true;
    }

    @Override
    @Transactional
    public Boolean deleteAllJob(List<Long> jobIds) {
        List<ScheduleJobPo> scheduleJobPos = this.baseMapper.selectBatchIds(jobIds);
        Boolean flag = scheduleUtils.deleteAllJob(cronScheduler, scheduler, scheduleJobPos);
        if (flag) {
            this.baseMapper.deleteBatchIds(jobIds);
        }
        return true;
    }

    @Override
    public ScheduleJobPo queryJobInfoByJobId(Long jobId) {
        if (jobId == null) return null;
        return this.baseMapper.selectById(jobId);
    }

    @Override
    public ScheduleJobPo queryJobByUserIdAndJobId(Long userId, Long jobId) {
        if (userId == null || jobId == null) return null;
        List<ScheduleJobPo> scheduleJobPos = this.baseMapper.queryJobByUserIdAndJobId(userId, jobId);
        return scheduleJobPos.get(0);
    }

    @Override
    public List<ScheduleJobPo> queryJobByUserId(Long userId) {
        if (userId == null) return null;
        List<ScheduleJobPo> scheduleJobPos = this.baseMapper.queryJobByUserIdAndJobId(userId, null);
        return scheduleJobPos;
    }

    @Override
    public Boolean updateJob(List<Long> jobIds, Integer status, BaseScheduler baseScheduler, Scheduler scheduler) {
        List<ScheduleJobPo> scheduleJobPos = this.baseMapper.selectBatchIds(jobIds);
        if (scheduleJobPos == null) return false;
        if (status.equals(ScheduleUtils.JobOperateEnum.DELETE.getValue())) {
            this.baseMapper.deleteBatchIds(jobIds);
        } else {
            updateBatchStatusByIds(jobIds, status);
        }
        if (status.equals(ScheduleUtils.JobOperateEnum.START.getValue())) {

            scheduleJobPos.stream().forEach(x -> {
                System.out.println(x);
                scheduleUtils.resumeJob(baseScheduler, scheduler, x.getJobId(), x.getType());
            });
        } else if (status.equals(ScheduleUtils.JobOperateEnum.PAUSE.getValue())) {
            scheduleJobPos.stream().forEach(x -> {
                scheduleUtils.pauseJob(baseScheduler, scheduler, x.getJobId(), x.getType());
            });
        } else {
            scheduleJobPos.stream().forEach(x -> {
                scheduleUtils.deleteJob(baseScheduler, scheduler, x.getJobId(), x.getType());
            });
        }
        return true;
    }


    @Override
    @Transactional
    public void updateBatchStatusByIds(List<Long> ids, Integer showStatus) {
        if (ids != null) {
            scheduleJobDao.updateBatchStatusByIds(ids, showStatus);
        }
    }
}
